package checkers3d.storage;

import checkers3d.logic.Game;
import checkers3d.logic.GameMaster;
import checkers3d.logic.IBoardObject;
import checkers3d.logic.Player;
import checkers3d.logic.PlayingSurface3D;
import checkers3d.logic.Point3D;
import checkers3d.presentation.GameEngine;
import checkers3d.presentation.RenderResourceBitmap;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.LinkedList;
import java.util.Scanner;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;

/**
 * Provides functionality for accessing data for playing scenarions. Can list
 * the availiable scenarios and load preview information. File formats are in
 * XML.
 * 
 * @author Ruben Acuna
 */
public class ScenarioManager
{
    /**
     * The relative path to the location where scenario information is stored.
     */
    public static final String LOCATION_SCENARIOS = ".//scenarios/";

    /**
     * Returns a RenderResourceBitmap preview image based on a given scenario
     * name.
     *
     * @param name The name of a scenario.
     * @return Preview image.
     */
    public static RenderResourceBitmap getScenarioRR(String name)
    {
        return new RenderResourceBitmap(ScenarioManager.LOCATION_SCENARIOS + name + ".png");
    }

    /**
     * Returns any data associated with a string (a 'fact' name) from a given
     * scenario.
     *
     * @param name The name of a scenario.
     * @param fact The name of the 'fact' to return data for.
     * @return Associated fact data.
     */
    public static String getScenarioFact(String name, String fact)
    {
        String description = new String();
        Document dom;

        try
        {
            dom = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(ScenarioManager.LOCATION_SCENARIOS + name + ".xml");

            description = getChildText(dom.getDocumentElement(), fact);
        }
        catch(Exception ioe)
        {
            Logger.log("getScenarioFact(" + name + ") - " + ioe);
        }

        return description;
    }

    /**
     * Given a parent node, and the name of a child with a text value, returns
     * that text value.
     *
     * @param parent A node whose child has a text value.
     * @param tagName Name of child with text value.
     * @return Text value from child.
     */
    private static String getChildText(Element parent, String tagName)
    {
        String text;
        Element textElement = (Element)parent.getElementsByTagName(tagName).item(0);

        text = textElement.getFirstChild().getNodeValue();

        return text;
    }

    /**
     * Loads the instant replay data from the InstantReplayData file.
     */
    static public void loadScenario(String filename, Player home, Player visitor) throws IOException{
        String homeName = home.getName();
        String visitorName = visitor.getName();
        PlayingSurface3D playingSurface3D;

        //set graphics for the home player.
        home.setCheckerRR("player1tokenchecker.png");
        home.setKingRR("player1tokenking.png");
        home.setWallRR("generictokenwall.png");
        home.setSafeRR("player1tokensafe.png");
        home.setMineRR("player1tokenmine.png");

        //set graphics for the visiting player.
        visitor.setCheckerRR("player2tokenchecker.png");
        visitor.setKingRR("player2tokenking.png");
        visitor.setWallRR("generictokenwall.png");
        visitor.setSafeRR("player2tokensafe.png");
        visitor.setMineRR("player2tokenmine.png");

        //temporarily change players name to be generic
        home.setName("Home");
        visitor.setName("Visitor");

        //scan.close();
        FileReader reader = new FileReader(filename);
        Scanner scanner = new Scanner(reader);

        playingSurface3D = DataManagerUtil.readPlayingSurface3D(scanner, home, visitor);

        for (int x = 0; x < playingSurface3D.getSizeX(); x++)
            for (int y = 0; y < playingSurface3D.getSizeY(); y++)
                for (int z = 0; z < playingSurface3D.getSizeZ(); z++)
                { 
                    for(IBoardObject object : playingSurface3D.getPositionObjects(new Point3D(x,y,z)))
                    {
                        if(object.getOwner() == home)
                            object.setOwner(home);
                        else
                            object.setOwner(visitor);
                    }
                }

        //restore players names.
        home.setName(homeName);
        visitor.setName(visitorName);

        GameMaster.getInstance().addGUIContainer(new Game(home, visitor, playingSurface3D, GameEngine.WINDOW_SIZE));

        reader.close();
        scanner.close();
    }
}